package com.towexin.application.system.service.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.towexin.application.system.domain.Authority;
import com.towexin.application.system.domain.Role;
import com.towexin.application.system.domain.RoleAuthority;
import com.towexin.application.system.mapper.AuthorityMapper;
import com.towexin.application.system.mapper.RoleMapper;
import com.towexin.application.system.service.AuthorityService;
import com.towexin.application.system.service.RoleAuthorityService;
import com.towexin.application.system.service.RoleService;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.subject.Subject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * TODO
 *
 * @author Towexin
 * @version 1.0
 * @date 2021/4/13 15:08
 */
@Service
@Transactional
public class RoleServiceImpl extends ServiceImpl<RoleMapper, Role> implements RoleService {
	@Autowired
	private RoleAuthorityService roleAuthorityService;

	@Autowired
	private AuthorityService authorityService;

	@Autowired
	private AuthorityMapper authorityMapper;

	// 保存或更新
	@Override
	public boolean saveOrUpdateOne(Role role) {
		role.setStatus(true);
		role.setRoleType("cac");
		role.setOpen(true);
		return saveOrUpdate(role);
	}

	// 通过id删除
	@Override
	public boolean deleteOneById(String id) {
		if (removeById(id)) {
			roleAuthorityService.remove(new QueryWrapper<RoleAuthority>().eq("r_id", id));
			return true;
		}
		return false;
	}

	// 获取用户有权操作的角色
	@Override
	public List<Role> selectAllByUserName() {
		Subject subject = SecurityUtils.getSubject();
		Role role = getByUserName(subject.getPrincipal().toString());
		if (role == null)
			return new ArrayList<>();

		return getChildRole(role.getId(), list());
	}

	// 获取角色树结构数据
	@Override
	public List<Map<String, Object>> selectRoleTree(boolean flag) {
		Subject subject = SecurityUtils.getSubject();
		Role role = getByUserName(subject.getPrincipal().toString());
		if (role == null)
			return new ArrayList<>();
		if (flag)
			return getCascadeMap(role.getPid(), list());
		return getCascadeMap(role.getId(), list());
	}

	// 获取对应角色权限
	@Override
	public List<Map<String, Object>> getAuthorityByRid(String id) {
		List<RoleAuthority> authorities = roleAuthorityService.list(new QueryWrapper<RoleAuthority>().eq("r_id", id));

		return getAuthority(JSON.parseArray(JSON.toJSONString(authorityService.selectAuthorityTree(false)), JSONObject.class), authorities);
	}

	//@Override
	//public List<Map<String, Object>> getDefaultAuthority() {
	//	List<RoleAuthority> authorities = roleAuthorityService.list(new QueryWrapper<RoleAuthority>().eq("r_id", "f6ea7a85-e06a-4d8e-9980-3a2c9020f65a"));
	//	return getAuthority(JSON.parseArray(JSON.toJSONString(authorityService.selectAuthorityTree(false)), JSONObject.class), authorities);
	//}

	// 分配权限
	@Override
	public boolean roleAuthorization(String rId, String authIdJson) {
		JSONArray jsonArray = JSONObject.parseArray(authIdJson);

		List<RoleAuthority> roleAuthorityList = roleAuthorityService
				.list(new QueryWrapper<RoleAuthority>().eq("r_id", rId));
		List<Authority> authorities = authorityMapper
				.selectAuthByUserName(SecurityUtils.getSubject().getPrincipal().toString());

		List<String> ids = new ArrayList<>();
		for (Authority authority : authorities) {
			for (RoleAuthority roleAuthority : roleAuthorityList) {
				if (authority.getId().equals(roleAuthority.getAId())) {
					ids.add(authority.getId());
				}
			}
		}
		if (ids.size() > 0)
			roleAuthorityService.remove(new QueryWrapper<RoleAuthority>().eq("r_id", rId).in("a_id", ids));

		List<RoleAuthority> roleAuthorities = new ArrayList<>();
		for (Object id : jsonArray) {
			RoleAuthority roleAuthority = new RoleAuthority();
			roleAuthority.setRId(rId);
			roleAuthority.setAId(id.toString());
			roleAuthorities.add(roleAuthority);
		}
		return jsonArray.size() <= 0 || roleAuthorityService.saveBatch(roleAuthorities);
	}

	@Override
	public boolean setDefaultRole(String id, boolean defaultRole) {
		Role role = new Role();
		role.setId(id);
		role.setDefaultRole(defaultRole);
		return updateById(role);
	}

	//@Override
	//public boolean roleAuthorization(String authIdJson) {
	//	JSONArray jsonArray = JSONObject.parseArray(authIdJson);
	//
	//	List<RoleAuthority> roleAuthorityList = roleAuthorityService
	//			.list(new QueryWrapper<RoleAuthority>().eq("r_id", "f6ea7a85-e06a-4d8e-9980-3a2c9020f65a"));
	//	List<Authority> authorities = authorityMapper
	//			.selectAuthByUserName(SecurityUtils.getSubject().getPrincipal().toString());
	//
	//	List<String> ids = new ArrayList<>();
	//	for (Authority authority : authorities) {
	//		for (RoleAuthority roleAuthority : roleAuthorityList) {
	//			if (authority.getId().equals(roleAuthority.getAId())) {
	//				ids.add(authority.getId());
	//			}
	//		}
	//	}
	//	if (ids.size() > 0)
	//		roleAuthorityService.remove(new QueryWrapper<RoleAuthority>().eq("r_id", "f6ea7a85-e06a-4d8e-9980-3a2c9020f65a").in("a_id", ids));
	//
	//	List<RoleAuthority> roleAuthorities = new ArrayList<>();
	//	for (Object id : jsonArray) {
	//		RoleAuthority roleAuthority = new RoleAuthority();
	//		roleAuthority.setRId("f6ea7a85-e06a-4d8e-9980-3a2c9020f65a");
	//		roleAuthority.setAId(id.toString());
	//		roleAuthorities.add(roleAuthority);
	//	}
	//	return jsonArray.size() <= 0 || roleAuthorityService.saveBatch(roleAuthorities);
	//}

	@Override
	public boolean changeStatus(String id, Boolean status) {
		Role role = new Role();
		role.setId(id);
		role.setStatus(status);
		return updateById(role);
	}

	// 获取用户角色
	@Override
	public Role getByUserName(String userName) {
		return baseMapper.selectByUserName(userName);
	}


	/**
	 * 获取角色标识（包含默认角色，排除冻结角色）
	 * @param userName
	 * @return
	 */
	@Override
	public List<String> getRoleAndDefaultMarkByUserName(String userName) {
		return baseMapper.selectMarkAndDefaultByUserName(userName);
	}

	@Override
	public List<String> getParentIdsByUserName(String userName) {
		return getParentId(baseMapper.selectByUserName(userName).getId(), list());
	}

	private List<Map<String, Object>> getCascadeMap(String pId, List<Role> roles) {
		List<Map<String, Object>> mapList = new ArrayList<>();

		for (Role role : roles) {
			if (role.getPid().equals(pId)) {
				Map<String, Object> map = new HashMap<>();
				map.put("name", role.getRoleName());
				map.put("value", role.getId());
				map.put("children", getCascadeMap(role.getId(), roles));
				if (!role.getStatus())
					map.put("name", map.get("name") + "【已冻结】");
				mapList.add(map);
			}
		}
		return mapList;
	}

	// 角色权限树递归
	protected List<Map<String, Object>> getAuthority(List<JSONObject> mapList,
			List<RoleAuthority> roleAuthorities) {
		List<Map<String, Object>> newMapList = new ArrayList<>();
		for (JSONObject map : mapList) {
			List<Map<String, Object>> childrenList = getAuthority(JSON.parseArray(JSON.toJSONString(map.get("children")), JSONObject.class),
					roleAuthorities);
			if (childrenList.size() > 0) {
				map.put("children", childrenList);
			} else {
				for (RoleAuthority roleAuthority : roleAuthorities) {
					if (map.get("id").equals(roleAuthority.getAId())) {
						map.put("checked", true);
					}
				}
			}
			newMapList.add(map);
		}
		return newMapList;
	}

	// 获取角色下的所有角色
	protected List<Role> getChildRole(String pId, List<Role> roles) {
		List<Role> roleList = new ArrayList<>();
		for (Role role : roles) {
			if (role.getPid().equals(pId)) {
				roleList.add(role);
				roleList.addAll(getChildRole(role.getId(), roles));
			}
		}
		return roleList;
	}

	// 获取上级角色id（包括自己）
	protected List<String> getParentId(String id, List<Role> roles) {
		List<String> ids = new ArrayList<>();
		ids.add(id);
		for (Role role : roles) {
			if (role.getId().equals(id) && !role.getPid().equals("no")) {
				ids.addAll(getParentId(role.getPid(), roles));
			}
		}
		return ids;
	}
}
